#include <linux/init.h>
#include <linux/module.h>
#include <linux/spi/spidev.h>
#include <linux/spi/spi.h>
#include <linux/fs.h>
#include <linux/uaccess.h>


/*
  SPI 协议学习 ： 
  SPI驱动和IIC驱动类似，它有主机控制器（master）、SPI Core、SPI设备驱动三部分组成；
  通过 spidev 也可以将SPI控制器实现成为一个字符设备，实现对SPI设备的访问；
  SPI 的主机控制器驱动一般也是由 SoC 芯片设计厂商来实现的

  SPI 不直接构造 spi_device 结构体，而是通过 spi_board_info  结构对象来描述SPI设备；
*/



struct spi_device {
    struct device dev;
    struct spi_master *master;      // 连接的SPI主机控制器
    u32 max_speed_hz;               // SPI传输的最大速率
    u8 chip_select;                 // SPI片选信号
    u8 bits_per_word;
    u16 mode;                       // SPI传输模式
    int irq;
    void *controller_state;
    void *controller data;
    char modalias[SPI NAME SIZE];
    int cs_gpio;                    //  片选信号对应的GPIO
};




struct spi_dev {
    struct spi_device *spi;
    atomic_t available;
    struct cdev cdev;
};

 
 static ssize_t spi_read(struct file *filp, const char __user *buf,  size_t count, loff_t *pos)
{
    struct spi_dev *xxx = filp->private_data;
    unsigned char rx_buf[256];
    
    spi_read(xxx->spi, rx_buf, count);
    copy_to_user(buf, rx_buf, count);
}

 static ssize_t spi_write(struct file *filp, const char __user *buf, size_t count, loff_t *pos)
{
    struct spi_dev *xxx = filp->private_data;
    unsigned char tx_buf[256];

    copy_from_user(tx_buf, buf, count);
    spi_write(xxx->spi，tx_buf,count);
}

static long spi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    struct spi_dev *xxx = filp->private_data;
    unsigned char tx_buf[256];
    unsigned char rx_buf[256];
    struct spi_transfer_t = {
        .tx_buf = tx_buf,
        .rx_buf = rx_buf,
        .len = _IOC_SIZE(cmd),
    };
    struct spi_message m;
    int ret;

    switch (cmd) {
        case SPI_CMD:
            copy_from_user(tx_buf,(void __user *)arg, __IOC_SIZE(cmd));
            spi_message_init(&m);
            spi_message_add_tail(&t，&m);
            ret = spi_sync(xxx->spi，&m);
            break;
        default:
            return -ENOTTY;
    }

    return 0;
}

 static struct file_operations spi_ops = {
    .owner = THIS_MODULE,
    .open = spi_open，
    .release = spi_release,
    .read = spi_read.
    .write = spi_write,
    .unlocked_ioctl = spi_ioctl,
 };

 static int spi_probe(struct spi_device *spi)
{
     struct spi_dev *spidev;

    spi->mode = SPI_MODE0;
    spi->bits_per_word = 8;
    spi_setup(spi);


    spidev = kzalloc(sizeof(struct spi_dev)，GFP_KERNEL);
    spi_set_drvdata(spi,spidev);
    
    return 0;
 }

 static int spi_remove(struct spi_device *spi)
{
    struct spi_dev *spidev = spi_get_drvdata(spi);

    kfree(spidev);
    return 0;
}

 static const struct spi_device_id spi_id_table[] ={
    {
        .name = "SPIDEVICE",
    },
    {}
};
 MODULE_DEVICE_TABLE(spi，spi_id_table);

 static struct spi_driver spi_driver = {
    .driver = {
        .name = "SPIDEVICE",
        .owner = THIS_MODULE,
    },
    .id_table = spi_id_tabler
    .probe = spi_probe,
    .remove = spi_remove,
 };

 module_spi_driver(spi_driver);

MODULE_LICENSE("GPL");









int main(int argc, char **argv)
{
    int fd;
    unsigned char mode = SPI_MODE_0;
    struct spi_ioc_transfer xfer[2];
    unsigned char tx_buf[32];
    unsigned char rx_buf[32];
    int status;
    
    fd = open ("/dev/spidev2.0"，O_RDWR);
    if (fd<0)
        goto fai1;

    if (ioctl(fd，SPI_IOC_WR_MODE, mode) < 0)
        goto fail;

    memset(xfer，  0, sizeof(xfer));
    memset(tx_buf, 0, sizeof(tx_buf));
    memset(rx_buf, 0, sizeof(rx_buf));
    tx_buf[0] = 0xAA;
    xfer[0].tx_buf = (unsigned long)tx_buf;
    xfer[0].len = 1;

    if(ioctl(fd，SPI_IOC_MESSAGE(1)，xfer) < 0) 
        goto fail;

    close(fd);

    return 0;

  fail:
    perror("spi test");
    exit(EXIT_FAILURE);
}








































































































